import models from "../models";
import { Op } from "sequelize";


export default class Service{
    constructor(){}
    static sourceNameToModel(sourceName){
        switch (sourceName) {
            case "users":
               return  models.User; 
            case "posts":
                return models.Post;
            case "movies":
                return models.Movie;
            case "cars":
                return models.Car;
            default:
               return null;
        }
    }
    static sourceNameQueryField(sourceName, filter){
        const $where = JSON.parse(filter);
        const searchQuery = fields => {
            
            const searchCondition = [];
            const queryConditon = {};
            for (let i = 0; i < fields.refs.length; i++) {
                const field = fields.refs[i];
                if($where[field]){
                    
                    queryConditon[field] = $where[field];
                }
                
            }
            for (let j = 0; j < fields.search.length; j++) {
                const field = fields.search[j];
                if($where.q){
                    const fieldObj = {};
                    fieldObj[field] = {
                        [Op.like]: '%'+$where.q+'%'
                    };
                    searchCondition.push(fieldObj);
                }
                
            }
            return searchCondition.length===0? queryConditon : {
                [Op.or]: searchCondition,
                ...queryConditon
            };
        }
        
        switch (sourceName) {
            case "users":
                return searchQuery({
                    refs: ["id"],
                    search: ['username', "mobile", "email"]
                })
            case "posts":
                return searchQuery({
                    refs: ["author", "id"],
                    search: ['title', "body", "breif"]
                })
            case "cars":
                return searchQuery({
                    refs: ["isUsable", "createdAt", "id"],
                    search: ['carNumber', "note"]
                })
            default:
               return {};
        }
    }
  
    static list(sourceName, condition){
        const {filter, range, sort} = condition;
        let sortParsed =  ['id','DESC'];
        if(typeof sort=== "string"){
            sortParsed = JSON.parse(sort);
            
        }
        let rangeParsed = [];
        if(typeof range!== "string"){
            rangeParsed=[0,9]
            
        }else{
            rangeParsed = JSON.parse(range);
        }
        const $where = this.sourceNameQueryField(sourceName, filter)
        const model = this.sourceNameToModel(sourceName);
        const rlt =  model.findAll({
            where: $where, 
            order: [sortParsed],
            offset: rangeParsed[0],
            limit: rangeParsed[1]+1
        });
        return rlt;
    }
    static count(sourceName, condition){
        const {filter, sort} = condition;
        let sortParsed =  ['id','DESC'];
        if(typeof sort=== "string"){
            sortParsed = JSON.parse(sort);
            
        }
        const $where = this.sourceNameQueryField(sourceName, filter)
        const model = this.sourceNameToModel(sourceName);
        const count = model.count({
            where: $where, 
            order: [sortParsed],
        });
        return count
    }
    static one(sourceName, condition){
        const model = this.sourceNameToModel(sourceName);
        const rlt = model.findOne(condition);
        return rlt
    }
    static updateOne(sourceName, data, condition){
        const model = this.sourceNameToModel(sourceName);
        const rlt = model.update(data, {where: condition});
        return rlt;
    }
    static createOne(sourceName, data){
        const model = this.sourceNameToModel(sourceName);
        const rlt = model.create(data);
        return rlt;
    }
    static delete(sourceName, condition){
        const model = this.sourceNameToModel(sourceName);
        const rlt = model.destroy({where: condition});
        return rlt;
    }
}